﻿using DBLayer.Datacontext;
using ModelLayer;
using System;
using System.Collections.Generic;
using System.Data.Linq.Mapping;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DBLayer
{
    public class DbAchievementOp
    {
        private DbUserOp dbUserOp;

        public DbAchievementOp()
        {
            dbUserOp = new DbUserOp();
        }

        /// <summary>
        /// Converts Achievement to datacontext Achievement
        /// </summary>
        /// <param name="achievement"></param>
        /// <returns>a datacontext achievment</returns>
        public DBAchievement ConvertAchievementToDbAchievement(Achievement achievement)
        {
            DBAchievement dbAchievement = new DBAchievement();
            dbAchievement.achievementId = achievement.AchievementId;
            dbAchievement.title = achievement.Title;
            dbAchievement.description = achievement.Description;
            dbAchievement.criteria = achievement.Criteria;
            dbAchievement.status = (int)achievement.CurrentStatus;
            dbAchievement.category = achievement.Category;
            dbAchievement.tag = achievement.Tag;
            dbAchievement.fk_achievementStarter = achievement.AchievementStarterId;

            return dbAchievement;
        }

        /// <summary>
        /// Insert Achievement in database (Not in userachievement)
        /// </summary>
        /// <param name="achievement"></param>
        /// <returns>int. 1 for succes. -1 for failure.</returns>
        public int InsertAchievement(Achievement achievement)
        {
            int result = -1;
            try
            {
                RLADataContext db = new RLADataContext();
                var dbach = ConvertAchievementToDbAchievement(achievement);
                db.DBAchievements.InsertOnSubmit(dbach);
                db.SubmitChanges();
                achievement.AchievementId = dbach.achievementId;

                //This is used to insert the achievement for the friends that are invited
                DbUserAchievementOp dbUserAchOp = new DbUserAchievementOp();

                if (achievement.Participants != null && achievement.Participants.Any())
                {
                    foreach (User participant in achievement.Participants)
                    {
                        UserAchievement userAch = new UserAchievement
                        {
                            User = participant,
                            Achievement = achievement,
                            CurrentStatus = UserAchievement.Status.Invited
                        };
                        dbUserAchOp.InsertUserAchievement(userAch);
                    }
                }

                //Commit til dbuserachievement
                /* Funktionaliteten skal ligge under ctr.
                 */
                db.SubmitChanges();
                result = dbach.achievementId;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            return result;
        }

        public Achievement ConvertDbAchievementToAchievement(DBAchievement dbAchievement)
        {
            Achievement achievement = new Achievement();
            achievement.AchievementId = dbAchievement.achievementId;
            achievement.Category = dbAchievement.category;
            achievement.Criteria = dbAchievement.criteria;
            achievement.CurrentStatus = (Achievement.Status)dbAchievement.status;
            achievement.Description = dbAchievement.description;
            achievement.Tag = dbAchievement.tag;
            achievement.Title = dbAchievement.title;
            achievement.AchievementStarterId = (int)dbAchievement.fk_achievementStarter;
            achievement.Participants = GetAchievementUserList(achievement);

            return achievement;
        }

        public UserAchievement ConvertDbUAToUA(DBUserAchievement dbUserAchievement)
        {
            Achievement ach = ConvertDbAchievementToAchievement(dbUserAchievement.DBAchievement);
            User user = dbUserOp.ConvertDbUserToUser(dbUserAchievement.DBUser);

            UserAchievement result = new UserAchievement
            {
                Achievement = ach,
                User = user,
                CurrentStatus = (UserAchievement.Status)dbUserAchievement.status
            };
            return result;
        }

        public List<User> GetAchievementUserList(Achievement achievement)
        {
            RLADataContext db = new RLADataContext();
            List<DBUserAchievement> achievementUserList = db.DBUserAchievements.Where(ua => ua.fk_AchievementId == achievement.AchievementId).ToList();

            List<User> userList = achievementUserList.Select(z => dbUserOp.ConvertDbUserToUser(z.DBUser)).ToList();

            return userList;
        }

        public int SetAchievementStatus(Achievement achievement)
        {
            RLADataContext db = new RLADataContext();
            DBAchievement dbAchievement = ConvertAchievementToDbAchievement(achievement);

            DBAchievement modifiedAchievement = db.DBAchievements.SingleOrDefault(a =>
                (a.achievementId == dbAchievement.achievementId));

            int result = -1;

            try
            {
                modifiedAchievement.status = (int)achievement.CurrentStatus;

                db.SubmitChanges();
                result = 1;
            }
            catch (SqlException e)
            {
                result = -2;
            }
            catch (Exception e)
            {
                result = -3;
                if (modifiedAchievement == null)
                {
                    result = -4;
                }
            }
            return result;
        }

        public UserAchievement GetUserAchievement(int userId, int achId)
        {
            RLADataContext db = new RLADataContext();

            DBUserAchievement dbUserAch = db.DBUserAchievements.First(ua => ua.DBAchievement.achievementId == achId
                                                         && ua.DBUser.userId == userId);

            UserAchievement result = ConvertDbUAToUA(dbUserAch);
            return result;
        }
    }
}